#include "mycrc.h"

mycrc::mycrc(void)
{
    reset();
}

mycrc::~mycrc()
{
}

void mycrc::reset(void)
{
    crc16 = 0xFFFF;
    crc32 = 0xFFFFFFFF;
}

void mycrc::push(void const *p_data, unsigned long size)
{
    crc16 = crc16_compute(p_data, size, &crc16);
    crc32 = crc32_compute(p_data, size, &crc32);
}

unsigned short mycrc::value16(void)
{
    return crc16;
}

unsigned long mycrc::value32(void)
{
    return crc32;
}

unsigned short mycrc::crc16_compute(void const *p_data, unsigned long size, unsigned short const *p_crc)
{
    unsigned short crc = *p_crc;
    unsigned char const *data = (unsigned char const *)p_data;

    for (unsigned long i = 0; i < size; i++)
    {
        crc  = (unsigned char)(crc >> 8) | (crc << 8);
        crc ^= data[i];
        crc ^= (unsigned char)(crc & 0xFF) >> 4;
        crc ^= (crc << 8) << 4;
        crc ^= ((crc & 0xFF) << 4) << 1;
    }

    return crc;
}

unsigned long mycrc::crc32_compute(void const *p_data, unsigned long size, unsigned long const *p_crc)
{
    unsigned long crc;
    unsigned char const *data = (unsigned char const *)p_data;
    crc =  ~(*p_crc);

    for (unsigned long i = 0; i < size; i++)
    {
        crc = crc ^ data[i];

        for (int j = 8; j > 0; j--)
        {
            crc = (crc >> 1) ^ (0xEDB88320U & ((crc & 1) ? 0xFFFFFFFF : 0));
        }
    }

    return ~crc;
}
